#include "flash_api.h"
#include "flash_board.h"

uint32_t FlashGetBootloaderFirmwareMaxFileSize(void)
{
  return BOOTLOADER_ACTUAL_OCCUPIED_SPACE;
}

void FlashDeleteBootloaderFirmwareFile(void)
{
  FlashEraseBlock(BOOTLOADER_START_SECTOR_ADDR, BOOTLOADER_ACTUAL_OCCUPIED_SPACE);
}

void FlashReadBootloaderFirmwareFile(uint32_t ReadAddrOffset, void *pFileOut, uint32_t FileSize)
{
  if (pFileOut != NULL)
  {
    if ((FileSize > 0) && (FileSize < BOOTLOADER_ACTUAL_OCCUPIED_SPACE))
    {
      uint32_t AddressOffset = BOOTLOADER_START_SECTOR_ADDR + ReadAddrOffset;
      if ((AddressOffset + FileSize) < BOOTLOADER_END_SECTOR_ADDR)
      {
        FlashReadCacheData(AddressOffset, pFileOut, FileSize);
      }
    }
  }
}

bool FlashWriteBootloaderFirmwareFile(uint32_t WriteAddrOffset, const void *pFileIn, uint32_t FileSize)
{
  if (pFileIn != NULL)
  {
    if ((FileSize > 0) && (FileSize < BOOTLOADER_ACTUAL_OCCUPIED_SPACE))
    {
      uint32_t AddressOffset = BOOTLOADER_START_SECTOR_ADDR + WriteAddrOffset;
      if ((AddressOffset + FileSize) < BOOTLOADER_END_SECTOR_ADDR)
      {
        return FlashWriteCacheDataToCheak(AddressOffset, pFileIn, FileSize);
      }
    }
  }

  return false;
}

uint32_t FlashGetApplictionFirmwareFileMaxSize(void)
{
  return APPLICATION_ACTUAL_OCCUPIED_SPACE;
}

void FlashDeleteApplictionFirmwareFile(void)
{
  FlashEraseBlock(APPLICATION_START_SECTOR_ADDR, APPLICATION_ACTUAL_OCCUPIED_SPACE);
}

void FlashReadApplictionFirmwareFile(uint32_t ReadAddrOffset, void *pFileOut, uint32_t FileSize)
{
  if (pFileOut != NULL)
  {
    if ((FileSize > 0) && (FileSize < APPLICATION_ACTUAL_OCCUPIED_SPACE))
    {
      uint32_t AddressOffset = APPLICATION_START_SECTOR_ADDR + ReadAddrOffset;
      if ((AddressOffset + FileSize) < APPLICATION_END_SECTOR_ADDR)
      {
        FlashReadCacheData(AddressOffset, pFileOut, FileSize);
      }
    }
  }
}

bool FlashWriteApplicationFirmwareFile(uint32_t WriteAddrOffset, const void *pFileIn, uint32_t FileSize)
{
  if (pFileIn != NULL)
  {
    if ((FileSize > 0) && (FileSize < APPLICATION_ACTUAL_OCCUPIED_SPACE))
    {
      uint32_t AddressOffset = APPLICATION_START_SECTOR_ADDR + WriteAddrOffset;
      if ((AddressOffset + FileSize) < APPLICATION_END_SECTOR_ADDR)
      {
        return FlashWriteCacheDataToCheak(AddressOffset, pFileIn, FileSize);
      }
    }
  }

  return false;
}

uint32_t FlashGetBackupBootloaderFirmwareFileSize(void)
{
  return FLASH_BOOTLOADER_BACKUP_ACTUAL_OCCUPIED_SPACE;
}

void FlashDeleteBackupBootloaderFirmwareFile(void)
{
  FlashEraseDataFlashBlock(FLASH_BOOTLOADER_BACKUP_START_SECTOR_ADDR, FLASH_BOOTLOADER_BACKUP_ACTUAL_OCCUPIED_SPACE);
}

void FlashReadBackupBootloaderFirmwareFile(uint32_t ReadAddrOffset, void *pFileOut, uint32_t FileSize)
{
  if (pFileOut != NULL)
  {
    if ((FileSize > 0) && (FileSize < FLASH_BOOTLOADER_BACKUP_ACTUAL_OCCUPIED_SPACE))
    {
      uint32_t AddressOffset = FLASH_BOOTLOADER_BACKUP_START_SECTOR_ADDR + ReadAddrOffset;
      if ((AddressOffset + FileSize) < FLASH_BOOTLOADER_BACKUP_END_SECTOR_ADDR)
      {
        FlashReadDataFlashCacheData(AddressOffset, pFileOut, FileSize);
      }
    }
  }
}

bool FlashWriteBackupBootloaderFirmwareFile(uint32_t WriteAddrOffset, const void *pFileIn, uint32_t FileSize)
{
  if (pFileIn != NULL)
  {
    if ((FileSize > 0) && (FileSize < FLASH_BOOTLOADER_BACKUP_ACTUAL_OCCUPIED_SPACE))
    {
      uint32_t AddressOffset = FLASH_BOOTLOADER_BACKUP_START_SECTOR_ADDR + WriteAddrOffset;
      if ((AddressOffset + FileSize) < FLASH_BOOTLOADER_BACKUP_END_SECTOR_ADDR)
      {
        return FlashWriteDataFlashCacheDataToCheak(AddressOffset, pFileIn, FileSize);
      }
    }
  }

  return false;
}

uint32_t FlashGetBackupBootloaderFirmwareCheckCode(uint32_t UpdateDataSize)
{
  uint32_t CheckCode = 0;
  uint8_t *pBackupFirmwareBuff = NULL;

  pBackupFirmwareBuff = FlashMolloc(FLASH_MAX_SECTOR_SIZE);
  if (pBackupFirmwareBuff != NULL)
  {
    uint32_t FilzeSize = 0, GetSize = 0;

    while (FilzeSize != UpdateDataSize)
    {
      FlashFeedWatchdog();
      memset(pBackupFirmwareBuff, 0, FLASH_MAX_SECTOR_SIZE);

      GetSize = UpdateDataSize - FilzeSize;
      if (GetSize > FLASH_MAX_SECTOR_SIZE)
      {
        GetSize = FLASH_MAX_SECTOR_SIZE;
      }

      FlashReadBackupBootloaderFirmwareFile(FilzeSize, pBackupFirmwareBuff, GetSize);
      for (uint32_t i = 0; i < GetSize; i++)
      {
        CheckCode += pBackupFirmwareBuff[i];
      }

      FilzeSize += GetSize;
    }

    FlashFree(pBackupFirmwareBuff);
  }
  else
  {
    PRINT("[error]: flash malloc failure.\r\n");
  }

  return CheckCode;
}

bool FlashUpdateBootloaderFirmware(void)
{
  return FlashBootloaderSectorDataMove();
}

uint32_t FlashGetDeviceParameterMaxFileSize(void)
{
  return FLASE_DEVICE_ACTUAL_OCCUPIED_SPACE;
}

void FlashDeleteDeviceParameterFile(void)
{
  FlashEraseDataFlashBlock(FLASH_START_ADDR_DEVICE_SECTOR, FLASE_DEVICE_ACTUAL_OCCUPIED_SPACE);
}

void FlashReadDeviceParameterFile(uint32_t ReadAddrOffset, void *pFileOut, uint32_t FileSize)
{
  if (pFileOut != NULL)
  {
    if (FileSize > 0)
    {
      uint32_t AddressOffset = FLASH_START_ADDR_DEVICE_SECTOR + ReadAddrOffset;
      if ((AddressOffset + FileSize) < FLASH_END_ADDR_DEVICE_SECTOR)
      {
        FlashReadDataFlashCacheData(AddressOffset, pFileOut, FileSize);
      }
    }
  }
}

bool FlashWriteDeviceParameterFile(uint32_t WriteAddrOffset, const void *pFileIn, uint32_t FileSize)
{
  if (pFileIn != NULL)
  {
    if (FileSize > 0)
    {
      uint32_t AddressOffset = FLASH_START_ADDR_DEVICE_SECTOR + WriteAddrOffset;
      if ((AddressOffset + FileSize) < FLASH_END_ADDR_DEVICE_SECTOR)
      {
        return FlashWriteDataFlashCacheDataToCheak(AddressOffset, pFileIn, FileSize);
      }
    }
  }

  return false;
}

uint32_t FlashGetCardHolderMaxFileSize(void)
{
  return FLASH_CARDHOLDER_ACTUAL_OCCUPIED_SPACE;
}

void FlashDeleteCardHolderFile(void)
{
  FlashEraseDataFlashBlock(FLASH_START_ADDR_CARDHOLDER_SECTOR, FLASH_CARDHOLDER_ACTUAL_OCCUPIED_SPACE);
}

void FlashReadCardHolderFile(uint32_t ReadAddrOffset, void *pFileOut, uint32_t FileSize)
{
  if (pFileOut != NULL)
  {
    if (FileSize > 0)
    {
      uint32_t AddressOffset = FLASH_START_ADDR_CARDHOLDER_SECTOR + ReadAddrOffset;
      if ((AddressOffset + FileSize) < FLASH_END_ADDR_CARDHOLDER_SECTOR)
      {
        FlashReadDataFlashCacheData(AddressOffset, pFileOut, FileSize);
      }
    }
  }
}

bool FlashWriteCardHolderFile(uint32_t WriteAddrOffset, const void *pFileIn, uint32_t FileSize)
{
  if (pFileIn != NULL)
  {
    if (FileSize > 0)
    {
      uint32_t AddressOffset = FLASH_START_ADDR_CARDHOLDER_SECTOR + WriteAddrOffset;
      if ((AddressOffset + FileSize) < FLASH_END_ADDR_CARDHOLDER_SECTOR)
      {
        return FlashWriteDataFlashCacheDataToCheak(AddressOffset, pFileIn, FileSize);
      }
    }
  }

  return false;
}

uint32_t FlashGetLogMaxFileSize(void)
{
  return FLASH_LOG_ACTUAL_OCCUPIED_SPACE;
}

void FlashDeleteLogFile(void)
{
  FlashEraseDataFlashBlock(FLASH_START_ADDR_LOG_SECTOR, FLASH_LOG_ACTUAL_OCCUPIED_SPACE);
}

void FlashReadLogFile(uint32_t ReadAddrOffset, void *pFileOut, uint32_t FileSize)
{
  if (pFileOut != NULL)
  {
    if (FileSize > 0)
    {
      uint32_t AddressOffset = FLASH_START_ADDR_LOG_SECTOR + ReadAddrOffset;

      if ((AddressOffset + FileSize) < FLASH_END_ADDR_LOG_SECTOR)
      {
        FlashReadDataFlashCacheData(AddressOffset, pFileOut, FileSize);
      }
    }
  }
}

bool FlashWriteLogFile(uint32_t WriteAddrOffset, const void *pFileIn, uint32_t FileSize)
{
  if (pFileIn != NULL)
  {
    if (FileSize > 0)
    {
      uint32_t AddressOffset = FLASH_START_ADDR_LOG_SECTOR + WriteAddrOffset;
      if ((AddressOffset + FileSize) < FLASH_END_ADDR_LOG_SECTOR)
      {
        return FlashWriteDataFlashCacheDataToCheak(AddressOffset, pFileIn, FileSize);
      }
    }
  }

  return false;
}

uint32_t FlashGetTemporaryFileMaxFileSize(void)
{
  // return FLASH_TEMPORARY_FILE_ACTUAL_OCCUPIED_SPACE;
}

void FlashDeleteTemporaryFile(void)
{
  // FlashEraseDataFlashBlock(FLASH_START_ADDR_TEMPORARY_FILE_SECTOR, FLASH_TEMPORARY_FILE_ACTUAL_OCCUPIED_SPACE);
}

void FlashReadTemporaryFile(uint32_t ReadAddrOffset, void *pFileOut, uint32_t FileSize)
{
  // if (pFileOut != NULL)
  // {
  //   if (FileSize > 0)
  //   {
  //     uint32_t AddressOffset = FLASH_START_ADDR_TEMPORARY_FILE_SECTOR + ReadAddrOffset;
  //     if ((AddressOffset + FileSize) < FLASH_END_ADDR_TEMPORARY_FILE_SECTOR)
  //     {
  //       FlashReadDataFlashCacheData(AddressOffset, pFileOut, FileSize);
  //     }
  //   }
  // }
}

bool FlashWriteTemporaryFile(uint32_t WriteAddrOffset, const void *pFileIn, uint32_t FileSize)
{
  // if (pFileIn != NULL)
  // {
  //   if (FileSize > 0)
  //   {
  //     uint32_t AddressOffset = FLASH_START_ADDR_TEMPORARY_FILE_SECTOR + WriteAddrOffset;
  //     if ((AddressOffset + FileSize) < FLASH_END_ADDR_TEMPORARY_FILE_SECTOR)
  //     {
  //       return FlashWriteDataFlashCacheDataToCheak(AddressOffset, pFileIn, FileSize);
  //     }
  //   }
  // }

  return false;
}


uint32_t FlashGetIoBoardFirmwareMaxFileSize(void)
{
  return IO_BOARD_FIRMWARE_ACTUAL_OCCUPIED_SPACE;
}

void FlashDeleteIoBoardFirmware(void)
{
  FlashEraseBlock(IO_BOARD_FIRMWARE_START_SECTOR, IO_BOARD_FIRMWARE_ACTUAL_OCCUPIED_SPACE);
}

void FlashReadIoBoardFirmware(uint32_t ReadAddrOffset, void *pFileOut, uint32_t FileSize)
{
  if (pFileOut!= NULL)
  {
    if ((FileSize > 0) && (FileSize < IO_BOARD_FIRMWARE_ACTUAL_OCCUPIED_SPACE))
    {
      uint32_t AddressOffset = IO_BOARD_FIRMWARE_START_SECTOR + ReadAddrOffset;
      if ((AddressOffset + FileSize) < IO_BOARD_FIRMWARE_END_SECTOR)
      {
        FlashReadCacheData(AddressOffset, pFileOut, FileSize);
      } 
    } 
  }
}

bool FlashWriteIoBoardFirmware(uint32_t WriteAddrOffset, const void *pFileIn, uint32_t FileSize)
{
  if (pFileIn!= NULL)
  {
    if ((FileSize > 0) && (FileSize < IO_BOARD_FIRMWARE_ACTUAL_OCCUPIED_SPACE))
    {
      uint32_t AddressOffset = IO_BOARD_FIRMWARE_START_SECTOR + WriteAddrOffset;
      if ((AddressOffset + FileSize) < IO_BOARD_FIRMWARE_END_SECTOR)
      {
        return FlashWriteCacheDataToCheak(AddressOffset, pFileIn, FileSize);
      } 
    } 
  }
  return false;
}

// bool FlashUpdateBootloaderFirmware(void)
// {
//   return FlashBootloaderSectorDataMove();
// }

